package tp.pr4.instructions;

import java.util.StringTokenizer;
import tp.pr4.NavigationModule;
import tp.pr4.RobotEngine;
import tp.pr4.instructions.exceptions.*;
import tp.pr4.items.ItemContainer;
import tp.pr4.Rotation;

/**
 * @author Alvaro Saez Hernando
 * @author Noel Clemente Montero 
 */
public class TurnInstruction implements Instruction {

	private static final String LINE_SEPARATOR = System.lineSeparator();
	
	private Rotation rotation;
	private RobotEngine robot;
	private NavigationModule navigation;
	
	/**
	 * Default constructor.
	 */
	public TurnInstruction() {
		this.rotation = null;
		this.robot = null;
		this.navigation = null;

	}
	
	/**
	 * Creates a TurnInstruction using a ID 
	 * @param id
	 */
	public TurnInstruction(Rotation rotation) {
		this.rotation = rotation;
		this.robot = null;
		this.navigation = null;
	}
	
	/**
	 * Parses the String returning a TurnInstruction instance or throwing a 
	 * WrongInstructionFormatException()
	 * @param cad text String to parse
	 * @return Instruction Reference pointing to an instance of a Instruction 
	 * subclass, if it is corresponding to the String cad
	 * @throws WrongInstructionFormatException When the String is not TURN LEFT 
	 * or RIGHT or GIRAR LEFT or RIGHT
	 */
	public Instruction parse(String cad) throws WrongInstructionFormatException {

		StringTokenizer st = new StringTokenizer(cad, " ");
		String words = st.nextToken().toUpperCase();
		
		if ((words.equals("TURN")) || (words.equals("GIRAR"))) {
			if (st.hasMoreTokens()) {
				String rotation = st.nextToken().toUpperCase();
				if (st.hasMoreTokens())
					throw new WrongInstructionFormatException("WALL·E says: I do not understand. Please repeat" + LINE_SEPARATOR);
				else if ((rotation.equals("LEFT")) || (rotation.equals("IZQUIERDA")))
					return new TurnInstruction(Rotation.LEFT);
				else if ((rotation.equals("RIGHT")) || (rotation.equals("DERECHA")))
					return new TurnInstruction(Rotation.RIGHT);
				else
					throw new WrongInstructionFormatException("WALL·E says: I do not understand. Please repeat" + LINE_SEPARATOR);
			}
			throw new WrongInstructionFormatException("WALL·E says: I do not understand. Please repeat" + LINE_SEPARATOR);
		} else
			throw new WrongInstructionFormatException("WALL·E says: I do not understand. Please repeat" + LINE_SEPARATOR);
	}

	/**
	 * Returns a description of the Instruction syntax. The string does 
	 * not end with the line separator. It is up to the caller adding it before printing.
	 * @return the command syntax TURN | GIRAR < LEFT|RIGHT >
	 */
	public String getHelp() {
		return "TURN|GIRAR <LEFT|RIGHT>" + LINE_SEPARATOR;
	}

	/**
	 * Set the execution context. The method receives the entire engine (engine, 
	 * navigation and the robot container) even though the actual implementation of execute() may not require it.
	 * @param engine The robot engine
	 * @param navigation The information about the game, i.e., the places, current 
	 * direction and current heading to navigate
	 * @param robotContainer The inventory of the robot
	 */
	public void configureContext(RobotEngine engine, NavigationModule navigation, ItemContainer robotContainer) {
		this.robot = engine;
		this.navigation = navigation;
	}

	/**
	 * Turns the robot left or right
	 * @throws InstructionExecutionException When the rotation is unknown
	 */
	public void execute() throws InstructionExecutionException {
		
		navigation.rotate(rotation);
		robot.addFuel(-5);
		System.out.println("WALL·E is looking at direction " + navigation.getCurrentHeading());
		robot.printRobotState();
		
	}

}
